<?xml version='1.0' encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

	<!-- upper-lower vars for use in case-insensitive sorting -->
	<xsl:variable name="lcletters">abcdefghijklmnopqrstuvwxyz</xsl:variable>
	<xsl:variable name="ucletters">ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable>

	<!-- variables used by url-encode below -->
	<!-- Characters we'll support. We could add control chars 0-31 and 127-159, but we won't. -->
	<xsl:variable name="url-ascii"> !"#$%&amp;'()*+,-./0123456789:;&lt;=&gt;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~</xsl:variable>
	<xsl:variable name="url-latin1">&#160;&#161;&#162;&#163;&#164;&#165;&#166;&#167;&#168;&#169;&#170;&#171;&#172;&#173;&#174;&#175;&#176;&#177;&#178;&#179;&#180;&#181;&#182;&#183;&#184;&#185;&#186;&#187;&#188;&#189;&#190;&#191;&#192;&#193;&#194;&#195;&#196;&#197;&#198;&#199;&#200;&#201;&#202;&#203;&#204;&#205;&#206;&#207;&#208;&#209;&#210;&#211;&#212;&#213;&#214;&#215;&#216;&#217;&#218;&#219;&#220;&#221;&#222;&#223;&#224;&#225;&#226;&#227;&#228;&#229;&#230;&#231;&#232;&#233;&#234;&#235;&#236;&#237;&#238;&#239;&#240;&#241;&#242;&#243;&#244;&#245;&#246;&#247;&#248;&#249;&#250;&#251;&#252;&#253;&#254;&#255;</xsl:variable>
	<!-- Characters that usually don't need to be escaped -->
	<xsl:variable name="url-safe">!'()*-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~</xsl:variable>
	<xsl:variable name="url-hex" >0123456789ABCDEF</xsl:variable>

	<!--
	date and time functions
	requires dates to be in W3C format: 2005-08-15T15:52:01+00:00
	-->

	<xsl:template name="format-timestamp">
		<xsl:param name="timestamp" select="''"/>
		<xsl:param name="part" select="''"/>
		<xsl:param name="format" select="'-'"/>
		<xsl:choose>
			<xsl:when test="contains($timestamp,',')">
				<!-- unsupported format, just return the date without messing with it -->
				<xsl:value-of select="$timestamp"/>
			</xsl:when>
			<xsl:otherwise>
				<xsl:choose>
					<!-- show a full timestamp -->
					<xsl:when test="$part = ''">
						<xsl:call-template name="format-date">
							<xsl:with-param name="timestamp" select="$timestamp"/>
							<xsl:with-param name="format" select="$format"/>
						</xsl:call-template>
						<xsl:text> </xsl:text>
						<xsl:call-template name="format-time">
							<xsl:with-param name="timestamp" select="$timestamp"/>
						</xsl:call-template>
					</xsl:when>
					<!-- show just the date part -->
					<xsl:when test="$part = 'timestamp'">
						<xsl:call-template name="format-date">
							<xsl:with-param name="timestamp" select="$timestamp"/>
							<xsl:with-param name="format" select="$format"/>
						</xsl:call-template>
					</xsl:when>
					<!-- show just the time part -->
					<xsl:when test="$part = 'Time'">
						<xsl:call-template name="format-time">
							<xsl:with-param name="timestamp" select="$timestamp"/>
						</xsl:call-template>
					</xsl:when>
				</xsl:choose>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>

	<xsl:template name="format-date">
		<xsl:param name="timestamp" select="''"/>
		<xsl:param name="format" select="'-'"/>
		<xsl:choose>
			<xsl:when test="string-length($timestamp) &gt; 1">
				<xsl:choose>
					<xsl:when test="string-length($timestamp) = 14">
						<!-- ISO date length -->
						<xsl:variable name="Year" select="substring($timestamp,1,4)"/>
						<xsl:variable name="Month" select="substring($timestamp,6,2)"/>
						<xsl:variable name="Day" select="substring($timestamp,9,2)"/>
						<xsl:choose>
							<xsl:when test="$format = '/'">
								<xsl:value-of select="concat($Month,'/',$Day,'/',$Year)"/>
							</xsl:when>
							<xsl:otherwise>
								<xsl:value-of select="concat($Year,'-',$Month,'-',$Day)"/>
							</xsl:otherwise>
						</xsl:choose>
					</xsl:when>
					<xsl:otherwise>
						<!-- if not, we'll assume it has dashes -->
						<xsl:variable name="Year" select="substring($timestamp,1,4)"/>
						<xsl:variable name="Month" select="substring($timestamp,6,2)"/>
						<xsl:variable name="Day" select="substring($timestamp,9,2)"/>
						<xsl:choose>
							<xsl:when test="$format = '/'">
								<xsl:value-of select="concat($Month,'/',$Day,'/',$Year)"/>
							</xsl:when>
							<xsl:otherwise>
								<xsl:value-of select="concat($Year,'-',$Month,'-',$Day)"/>
							</xsl:otherwise>
						</xsl:choose>
					</xsl:otherwise>
				</xsl:choose>
			</xsl:when>
			<xsl:otherwise>
				<xsl:text> </xsl:text>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>

	<xsl:template name="format-time">
		<xsl:param name="timestamp" select="''"/>
		<xsl:if test="$timestamp">
			<xsl:variable name="Hour" select="substring($timestamp,12,2)*1"/>
			<xsl:variable name="Minutes" select="substring($timestamp,15,2)"/>
			<xsl:choose>
				<xsl:when test="$Hour &gt; 12">
					<xsl:value-of select="concat(number($Hour) - 12,':',$Minutes,' PM')"/>
				</xsl:when>
				<xsl:when test="$Hour &gt; 11">
					<xsl:value-of select="concat($Hour,':',$Minutes,' PM')"/>
				</xsl:when>
				<xsl:otherwise>
					<xsl:value-of select="concat($Hour,':',$Minutes,' AM')"/>
				</xsl:otherwise>
			</xsl:choose>

		</xsl:if>
	</xsl:template>

	<xsl:template name="string-replace">
		<xsl:param name="str"/>
		<xsl:param name="find"/>
		<xsl:param name="replace"/>
		<xsl:choose>
			<xsl:when test="contains($str, $find)">
				<xsl:value-of select="concat(substring-before($str, $find), $replace)"/>
				<xsl:call-template name="string-replace">
					<xsl:with-param name="str" select="substring-after($str, $find)"/>
					<xsl:with-param name="find" select="$find"/>
					<xsl:with-param name="replace" select="$replace"/>
				</xsl:call-template>
			</xsl:when>
			<xsl:otherwise>
				<xsl:value-of select="$str"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>

	<xsl:template name="json-encode">
		<xsl:param name="str"/>
		<xsl:variable name="apos">'</xsl:variable>
		<xsl:variable name="dquo">"</xsl:variable>
		<!-- line feed -->
		<xsl:variable name="one">
			<xsl:call-template name="string-replace">
				<xsl:with-param name="str" select="$str"/>
				<xsl:with-param name="find" select="'&#10;'"/>
				<xsl:with-param name="replace" select="''"/>
			</xsl:call-template>
		</xsl:variable>
		<!-- carriage return -->
		<xsl:variable name="two">
			<xsl:call-template name="string-replace">
				<xsl:with-param name="str" select="$one"/>
				<xsl:with-param name="find" select="'&#13;'"/>
				<xsl:with-param name="replace" select="''"/>
			</xsl:call-template>
		</xsl:variable>
		<!-- tab -->
		<xsl:variable name="three">
			<xsl:call-template name="string-replace">
				<xsl:with-param name="str" select="$two"/>
				<xsl:with-param name="find" select="'&#09;'"/>
				<xsl:with-param name="replace" select="''"/>
			</xsl:call-template>
		</xsl:variable>
		<!-- double quote -->
		<xsl:variable name="four">
			<xsl:call-template name="string-replace">
				<xsl:with-param name="str" select="$three"/>
				<xsl:with-param name="find" select="$dquo"/>
				<!-- <xsl:with-param name="replace" select="concat('\',$dquo)"/> -->
				<xsl:with-param name="replace" select="concat('&amp;','#34;')"/>
			</xsl:call-template>
		</xsl:variable>
		<!-- single quote -->
		<xsl:variable name="five">
			<xsl:call-template name="string-replace">
				<xsl:with-param name="str" select="$four"/>
				<xsl:with-param name="find" select="$apos"/>
				<!-- <xsl:with-param name="replace" select="concat('\',$apos)"/> -->
				<xsl:with-param name="replace"><xsl:text>&#8217;</xsl:text></xsl:with-param>
			</xsl:call-template>
		</xsl:variable>
		<xsl:value-of select="$five"/>
	</xsl:template>

	<!-- got this voodoo here: http://skew.org/xml/stylesheets/url-encode/url-encode.xsl -->
	<xsl:template name="url-encode">
		<xsl:param name="str"/>
		<xsl:if test="$str">
			<xsl:variable name="first-char" select="substring($str,1,1)"/>
			<xsl:choose>
				<xsl:when test="contains($url-safe,$first-char)">
					<xsl:value-of select="$first-char"/>
				</xsl:when>
				<xsl:otherwise>
					<xsl:variable name="codepoint">
						<xsl:choose>
							<xsl:when test="contains($url-ascii,$first-char)">
								<xsl:value-of select="string-length(substring-before($url-ascii,$first-char)) + 32"/>
							</xsl:when>
							<xsl:when test="contains($url-latin1,$first-char)">
								<xsl:value-of select="string-length(substring-before($url-latin1,$first-char)) + 160"/>
							</xsl:when>
							<xsl:otherwise>
								<xsl:message terminate="no">Warning: string contains a character that is out of range! Substituting "?".</xsl:message>
								<xsl:text>63</xsl:text>
							</xsl:otherwise>
						</xsl:choose>
					</xsl:variable>
					<xsl:variable name="hex-digit1" select="substring($url-hex,floor($codepoint div 16) + 1,1)"/>
					<xsl:variable name="hex-digit2" select="substring($url-hex,$codepoint mod 16 + 1,1)"/>
					<xsl:value-of select="concat('%',$hex-digit1,$hex-digit2)"/>
				</xsl:otherwise>
			</xsl:choose>
			<xsl:if test="string-length($str) &gt; 1">
				<xsl:call-template name="url-encode">
					<xsl:with-param name="str" select="substring($str,2)"/>
				</xsl:call-template>
			</xsl:if>
		</xsl:if>
	</xsl:template>

</xsl:stylesheet>
